#pragma once

#include <AVUIContentControl.h>
#include <AVUIWindowCollection.h>

namespace AVUI {

class WindowFrame;

class Window : public ContentControl
{
    friend class WindowCollection;
    friend class WindowManager;
    friend class WindowFrame;
    friend class Mouse;
public:
    Window() : m_isShowingAsDialog(false), m_pWindowNext(NULL), m_pWindowPrevious(NULL) { Initialize(); };
    ~Window() { };

    DECLARE_ELEMENT(Window, ContentControl);

    DECLARE_DEPENDENCY_PROPERTY(Title);
    TRefCountedPtr<String> get_Title() { return (String*)(Object*)GetValue(get_TitleProperty()); }
    void set_Title(String* pValue) { SetValue(get_TitleProperty(), (Object*)pValue); } 

    DECLARE_DEPENDENCY_PROPERTY(Topmost);
    bool get_Topmost() { return AVUI::UnboxValue<bool>(GetValue(get_TopmostProperty())); }
    void set_Topmost(bool value) { SetValue(get_TopmostProperty(), AVUI::BoxValue(value)); } 

    DECLARE_DEPENDENCY_PROPERTY(ResizeMode);
    ResizeMode::Enum get_ResizeMode() { return (ResizeMode::Enum)(AVUI::UnboxValue<int>(GetValue(get_ResizeModeProperty()))); }
    void set_ResizeMode(ResizeMode::Enum value) { SetValue(get_ResizeModeProperty(), AVUI::BoxValue<int>(value)); } 

    DECLARE_DEPENDENCY_PROPERTY(WindowState);
    WindowState::Enum get_WindowState() { return (WindowState::Enum)(AVUI::UnboxValue<int>(GetValue(get_WindowStateProperty()))); }
    void set_WindowState(WindowState::Enum value) { SetValue(get_WindowStateProperty(), AVUI::BoxValue<int>(value)); } 

    DECLARE_DEPENDENCY_PROPERTY(WindowStyle);
    WindowStyle::Enum get_WindowStyle() { return (WindowStyle::Enum)(AVUI::UnboxValue<int>(GetValue(get_WindowStyleProperty()))); }
    void set_WindowStyle(WindowStyle::Enum value) { SetValue(get_WindowStyleProperty(), AVUI::BoxValue<int>(value)); } 

    WindowCollection* get_OwnedWindows() { return &m_ownedWindows; }

    Window* get_Owner() { return m_pOwnerWindow; }
    void set_Owner(Window* pNewOwner);    

    Window* get_ZOrderNext() { return m_pWindowNext; }
    Window* get_ZOrderPrevious() { return m_pWindowPrevious; }

    void Activate();
    void Show();
    void Hide();
    void Close();
    void ShowDialog();
    void EndDialog();

    bool get_IsShowing() { return get_Visibility() == Visibility::Visible; }
    bool get_IsShowingAsDialog() { return m_isShowingAsDialog; }

    int get_VisualChildrenCount();
    Visual* GetVisualChild(int idx);

    Point get_WindowLocation() const { return m_windowArea.get_Location(); }
    Size get_WindowSize() const { return m_windowArea.get_Size(); }

protected:

    virtual void OnContentChanged(Object* pOldContent, Object* pNewContent);

    virtual void OnWindowActivated();
    virtual void OnWindowDeactivated();

    virtual Size MeasureOverride(const Size& constraintSize);
    virtual Size ArrangeOverride(const Size& constraintSize);

    WindowCollection m_ownedWindows;
    TWeakPtr<Window> m_pOwnerWindow;

    virtual TRefCountedPtr<Geometry> GetLayoutClip(const Size& layoutSlotSize) AVUI_OVERRIDE;

private:
    static void StaticConstructor();
    void PostContentRendered();
    static void OnContentRenderedStatic(Object* pSender, Object* pArgs) { ((Window*)pArgs)->OnContentRendered(); };
    void OnContentRendered();

    void OnPresentationSourceSizeChanged();

    static void OnResizeModeChanged(DependencyObject* pDO, DependencyPropertyChangedEventArgs* e);
    static void OnWindowStateChanged(DependencyObject* pDO, DependencyPropertyChangedEventArgs* e);
    static void OnWindowStyleChanged(DependencyObject* pDO, DependencyPropertyChangedEventArgs* e);

    void set_WindowLocation(const Point& newLocation) { m_windowArea.set_Location(newLocation); }
    void set_WindowSize(const Size& newSize) { m_windowArea.set_Size(newSize); InvalidateMeasure(); }

    void Initialize();
    bool m_isShowingAsDialog;

    // Sorted / Z order
    Window* m_pWindowNext;
    Window* m_pWindowPrevious;

    TRefCountedPtr<WindowFrame> m_pWindowFrame;
    Rect m_windowArea;
    Rect m_restoreArea;
};


}; // namespace AVUI
